
#if !defined(AFX_GLUTBIND_H__0A8840CC_3632_4286_B67D_C4767C7269E3__INCLUDED_)
#define AFX_GLUTBIND_H__0A8840CC_3632_4286_B67D_C4767C7269E3__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "SQFunction.h"
#include<GL/glut.h>
#define REGGLOBALSQFUNC(NAME) register_global_func(v,sq_##NAME,_SC(#NAME));

#define DECLARECALLBACKFUNCVOID(NAME)\
	SqFunction<void> _##NAME;\
	void __##NAME()\
{\
	_##NAME();\
}\
	void set_##NAME(SqFunction<void>& fun)\
{\
	_##NAME = fun;\
	NAME(&__##NAME);	\
}\
	SQInteger sq_##NAME(HSQUIRRELVM v)\
{\
	const SQChar *s;\
	if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){\
	set_##NAME(SqFunction<void>(v,s));\
	return 1;\
	}\
	return 0;\
}
#define DECLARECALLBACKFUNCVOID1(P1,NAME)\
	SqFunction<void> _##NAME;\
	void __##NAME(P1 p1)\
{\
	_##NAME(p1);\
}\
	void set_##NAME(SqFunction<void>& fun)\
{\
	_##NAME = fun;\
	NAME(&__##NAME);	\
}\
	SQInteger sq_##NAME(HSQUIRRELVM v)\
{\
	const SQChar *s;\
	if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){\
	set_##NAME(SqFunction<void>(v,s));\
	return 1;\
	}\
	return 0;\
}

#define DECLARECALLBACKFUNCVOID2(P1,P2,NAME)\
	SqFunction<void> _##NAME;\
	void __##NAME(P1 p1,P2 p2)\
	{\
	_##NAME(p1,p2);\
	}\
	void set_##NAME(SqFunction<void>& fun)\
	{\
	_##NAME = fun;\
	NAME(&__##NAME);	\
	}\
	SQInteger sq_##NAME(HSQUIRRELVM v)\
	{\
	const SQChar *s;\
	if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){\
	set_##NAME(SqFunction<void>(v,s));\
	return 1;\
	}\
	return 0;\
	}
#define DECLARECALLBACKFUNCVOID3(P1,P2,P3,NAME)\
	SqFunction<void> _##NAME;\
	void __##NAME(P1 p1,P2 p2,P3 p3)\
{\
	_##NAME(p1,p2,p3);\
}\
	void set_##NAME(SqFunction<void>& fun)\
{\
	_##NAME = fun;\
	NAME(&__##NAME);	\
}\
	SQInteger sq_##NAME(HSQUIRRELVM v)\
{\
	const SQChar *s;\
	if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){\
	set_##NAME(SqFunction<void>(v,s));\
	return 1;\
	}\
	return 0;\
}
#define DECLARECALLBACKFUNCVOID4(P1,P2,P3,P4,NAME)\
	SqFunction<void> _##NAME;\
	void __##NAME(P1 p1,P2 p2,P3 p3,P4 p4)\
{\
	_##NAME(p1,p2,p3,p4);\
}\
	void set_##NAME(SqFunction<void>& fun)\
{\
	_##NAME = fun;\
	NAME(&__##NAME);	\
}\
	SQInteger sq_##NAME(HSQUIRRELVM v)\
{\
	const SQChar *s;\
	if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){\
	set_##NAME(SqFunction<void>(v,s));\
	return 1;\
	}\
	return 0;\
}



DECLARECALLBACKFUNCVOID(glutDisplayFunc)
DECLARECALLBACKFUNCVOID(glutIdleFunc)
DECLARECALLBACKFUNCVOID2(int,int,glutReshapeFunc)
DECLARECALLBACKFUNCVOID3(unsigned char,int,int,glutKeyboardFunc)
DECLARECALLBACKFUNCVOID3(int,int,int,glutSpecialFunc)
DECLARECALLBACKFUNCVOID3(unsigned char,int,int,glutKeyboardUpFunc)
DECLARECALLBACKFUNCVOID3(int,int,int,glutSpecialUpFunc)
DECLARECALLBACKFUNCVOID1(int,glutEntryFunc)
DECLARECALLBACKFUNCVOID2(int,int, glutPassiveMotionFunc)
DECLARECALLBACKFUNCVOID2(int,int, glutMotionFunc)
DECLARECALLBACKFUNCVOID4(int,int,int,int, glutMouseFunc)


// void printx(char* str)
// {
// 	printf("%s",str);
// }
// void printxx(char** str)
// {
// 	printf("%s",*str);
// }
// void xxBind(HSQUIRRELVM v)
// {
// RegisterGlobal(v,printx,_SC("printx"));
// RegisterGlobal(v,printxx,_SC("printxx"));
// }
SQInteger sq_glutInit(HSQUIRRELVM v)
{
	int argct =1;
	char *argvt = "sqglut.nut";
	glutInit(&argct, &argvt);

	return 1;
}

#if 0
template<typename Func,typename CallBack>
inline void RegisterGlobalCallbackCaller(HSQUIRRELVM v,Func func,CallBack calbak, const SQChar * name) {
	sq_pushroottable(v);
	RegisterCallbackCaller(v,func,calbak,name);
	sq_poptop(v); // Remove root table.
} // RegisterGlobal
template<typename Func,typename CallBack>
inline void RegisterCallbackCaller(HSQUIRRELVM v,Func func,CallBack calbak,const SQChar * name) {
	sq_pushstring(v,name,-1);
	sq_pushdirectclosureCallbackCaller(v,func,calbak,0);
	sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
} // Register
template<typename Func,typename CallBack>
inline void sq_pushdirectclosureCallbackCaller(HSQUIRRELVM v,Func func,CallBack calbak,SQUnsignedInteger nupvalues) {
	SQUserPointer up = sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
	memcpy(up,&func,sizeof(func));
	sq_newclosure(v,DirectCallFunction<Func>::Dispatch,nupvalues+1);
} // sq_pushdirectclosure

template<typename Func,typename CallBack>
struct DirectCallCallbackCallerFunction {
	static inline int Dispatch(HSQUIRRELVM v) {
		StackHandler sa(v);
		int paramCount = sa.GetParamCount();
		Func * func = (Func *)sa.GetUserData(paramCount);
		return Call(*func,v,2);
	} // Dispatch
};
#endif
//////////////////////////////////////////////////////////////////////////

void openglBind(HSQUIRRELVM v)
{
	//////////////////////////////////////////////////////////////////////////
	//OpenGl Constants



	RegisterGlobalConstant(v,GL_POINTS,_SC("GL_POINTS"));
	RegisterGlobalConstant(v,GL_LINES,_SC("GL_LINES"));
	RegisterGlobalConstant(v,GL_LINE_LOOP,_SC("GL_LINE_LOOP"));
	RegisterGlobalConstant(v,GL_LINE_STRIP,_SC("GL_LINE_STRIP"));
	RegisterGlobalConstant(v,GL_TRIANGLES,_SC("GL_TRIANGLES"));
	RegisterGlobalConstant(v,GL_TRIANGLE_STRIP,_SC("GL_TRIANGLE_STRIP"));
	RegisterGlobalConstant(v,GL_TRIANGLE_FAN,_SC("GL_TRIANGLE_FAN"));
	RegisterGlobalConstant(v,GL_QUADS,_SC("GL_QUADS"));
	RegisterGlobalConstant(v,GL_QUAD_STRIP,_SC("GL_QUAD_STRIP"));
	RegisterGlobalConstant(v,GL_POLYGON,_SC("GL_POLYGON"));
	RegisterGlobalConstant(v,GL_SMOOTH,_SC("GL_SMOOTH"));
	RegisterGlobalConstant(v,GL_FLAT,_SC("GL_FLAT"));

	RegisterGlobalConstant(v,GL_DEPTH_BUFFER_BIT,_SC("GL_DEPTH_BUFFER_BIT"));
	RegisterGlobalConstant(v,GL_MODELVIEW,_SC("GL_MODELVIEW"));
	RegisterGlobalConstant(v,GL_PROJECTION,_SC("GL_PROJECTION"));
	RegisterGlobalConstant(v,GL_COLOR_BUFFER_BIT,_SC("GL_COLOR_BUFFER_BIT"));
	RegisterGlobalConstant(v,GL_TEXTURE,_SC("GL_TEXTURE"));
	RegisterGlobalConstant(v,GL_DEPTH_TEST,_SC("GL_DEPTH_TEST"));

	RegisterGlobalConstant(v,GL_COMPILE,_SC("GL_COMPILE"));

	RegisterGlobalConstant(v,GL_LIGHTING,_SC("GL_LIGHTING"));
	RegisterGlobalConstant(v,GL_LIGHT0,_SC("GL_LIGHT0"));
	RegisterGlobalConstant(v,GL_LIGHT1,_SC("GL_LIGHT1"));
	RegisterGlobalConstant(v,GL_LIGHT2,_SC("GL_LIGHT2"));
	RegisterGlobalConstant(v,GL_LIGHT3,_SC("GL_LIGHT3"));
	RegisterGlobalConstant(v,GL_LIGHT4,_SC("GL_LIGHT4"));
	RegisterGlobalConstant(v,GL_LIGHT5,_SC("GL_LIGHT5"));
	RegisterGlobalConstant(v,GL_LIGHT6,_SC("GL_LIGHT6"));
	RegisterGlobalConstant(v,GL_LIGHT7,_SC("GL_LIGHT7"));

	RegisterGlobalConstant(v,GL_AMBIENT,_SC("GL_AMBIENT"));
	RegisterGlobalConstant(v,GL_DIFFUSE,_SC("GL_DIFFUSE"));
	RegisterGlobalConstant(v,GL_SPECULAR,_SC("GL_SPECULAR"));
	RegisterGlobalConstant(v,GL_POSITION,_SC("GL_POSITION"));
	RegisterGlobalConstant(v,GL_SPOT_DIRECTION,_SC("GL_SPOT_DIRECTION"));
	RegisterGlobalConstant(v,GL_SPOT_EXPONENT,_SC("GL_SPOT_EXPONENT"));
	RegisterGlobalConstant(v,GL_SPOT_CUTOFF,_SC("GL_SPOT_CUTOFF"));
	RegisterGlobalConstant(v,GL_CONSTANT_ATTENUATION,_SC("GL_CONSTANT_ATTENUATION"));
	RegisterGlobalConstant(v,GL_LINEAR_ATTENUATION,_SC("GL_LINEAR_ATTENUATION"));
	RegisterGlobalConstant(v,GL_QUADRATIC_ATTENUATION,_SC("GL_QUADRATIC_ATTENUATION"));

	RegisterGlobalConstant(v,GL_LIGHT_MODEL_AMBIENT,_SC("GL_LIGHT_MODEL_AMBIENT"));

	RegisterGlobalConstant(v,GL_NONE,_SC("GL_NONE"));
	RegisterGlobalConstant(v,GL_FRONT_LEFT,_SC("GL_FRONT_LEFT"));
	RegisterGlobalConstant(v,GL_FRONT_RIGHT,_SC("GL_FRONT_RIGHT"));
	RegisterGlobalConstant(v,GL_BACK_LEFT,_SC("GL_BACK_LEFT"));
	RegisterGlobalConstant(v,GL_FRONT,_SC("GL_FRONT"));
	RegisterGlobalConstant(v,GL_BACK,_SC("GL_BACK"));
	RegisterGlobalConstant(v,GL_LEFT,_SC("GL_LEFT"));
	RegisterGlobalConstant(v,GL_RIGHT,_SC("GL_RIGHT"));
	RegisterGlobalConstant(v,GL_FRONT_AND_BACK,_SC("GL_FRONT_AND_BACK"));
	RegisterGlobalConstant(v,GL_AUX0,_SC("GL_AUX0"));
	RegisterGlobalConstant(v,GL_AUX1,_SC("GL_AUX1"));
	RegisterGlobalConstant(v,GL_AUX2,_SC("GL_AUX2"));
	RegisterGlobalConstant(v,GL_AUX3,_SC("GL_AUX3"));

	RegisterGlobalConstant(v,GL_SHININESS,_SC("GL_SHININESS"));
	RegisterGlobalConstant(v,GL_EMISSION,_SC("GL_EMISSION"));
	RegisterGlobalConstant(v,GL_AMBIENT_AND_DIFFUSE,_SC("GL_AMBIENT_AND_DIFFUSE"));
	RegisterGlobalConstant(v,GL_COLOR_INDEXES,_SC("GL_COLOR_INDEXES"));


	RegisterGlobalConstant(v,GL_AUX3,_SC("GL_AUX3"));
	//////////////////////////////////////////////////////////////////////////
	//OpenGlRegisterGlobalConstant(v,GL_DEPTH_TEST,_SC("GL_DEPTH_TEST"));
	RegisterGlobal(v,glViewport,_SC("glViewport"));
	RegisterGlobal(v,glRotatef,_SC("glRotatef"));
	RegisterGlobal(v,glClear,_SC("glClear"));	
	RegisterGlobal(v,glVertex3f,_SC("glVertex3f"));
	RegisterGlobal(v,glColor3f,_SC("glColor3f"));
	RegisterGlobal(v,glBegin,_SC("glBegin"));	
	RegisterGlobal(v,glMatrixMode,_SC("glMatrixMode"));	
	RegisterGlobal(v, glEnd,_SC("glEnd"));
	RegisterGlobal(v, glPushMatrix,_SC("glPushMatrix"));
	RegisterGlobal(v, glFlush,_SC("glFlush"));
	RegisterGlobal(v, glPopMatrix,_SC("glPopMatrix"));
	RegisterGlobal(v, glLoadIdentity,_SC("glLoadIdentity"));
	RegisterGlobal(v, glTranslatef,_SC("glTranslatef"));
	RegisterGlobal(v, glNewList,_SC("glNewList"));
	RegisterGlobal(v, glEndList,_SC("glEndList"));
	RegisterGlobal(v, glEnable,_SC("glEnable"));
	RegisterGlobal(v, glGenLists,_SC("glGenLists"));
	RegisterGlobal(v, glCallList,_SC("glCallList"));

	RegisterGlobal(v,glEnable ,_SC("glEnable"));
	RegisterGlobal(v,glDisable ,_SC("glDisable"));
	RegisterGlobal(v,glColorMaterial,_SC("glColorMaterial"));
	RegisterGlobal(v,glMaterialfv,_SC("glMaterialfv"));
	RegisterGlobal(v,glColorMaterial,_SC("glColorMaterial"));
	RegisterGlobal(v,glClearColor,_SC("glClearColor"));
	RegisterGlobal(v,glShadeModel,_SC("glShadeModel"));
	RegisterGlobal(v,glLightModelf,_SC("glLightModelf"));

}
void gluBind(HSQUIRRELVM v)
{
	//////////////////////////////////////////////////////////////////////////
	//glu
	//	register_global_func(v,sq_voidFuncCap4<void(__stdcall*)( double,double,double,double),gluPerspective,void,double,double,double,double>,_SC("gluPerspective"));
	// 	register_global_func(v,sq_voidFuncCap9<void(__stdcall*)( double,double,double,double,double,double,double,double,double),gluLookAt,
	// 		void,double,double,double,double,double,double,double,double,double>,_SC("gluLookAt"));

	RegisterGlobal(v,gluPerspective,_SC("gluPerspective"));
	RegisterGlobal(v,gluLookAt,_SC("gluLookAt"));

}
void glutBind(HSQUIRRELVM v)
{
	openglBind(v);
	gluBind(v);
	//////////////////////////////////////////////////////////////////////////
	//glut Constants
	RegisterGlobalConstant(v,GLUT_DEPTH,_SC("GLUT_DEPTH"));
	RegisterGlobalConstant(v,GLUT_SINGLE,_SC("GLUT_SINGLE"));
	RegisterGlobalConstant(v,GLUT_RGB,_SC("GLUT_RGB"));
	RegisterGlobalConstant(v,GLUT_RGBA,_SC("GLUT_RGBA"));
	RegisterGlobalConstant(v,GLUT_DOUBLE,_SC("GLUT_DOUBLE"));
	RegisterGlobalConstant(v,GLUT_KEY_F1,_SC("GLUT_KEY_F1"));
	RegisterGlobalConstant(v,GLUT_KEY_F2,_SC("GLUT_KEY_F2"));
	RegisterGlobalConstant(v,GLUT_KEY_F3,_SC("GLUT_KEY_F3"));
	RegisterGlobalConstant(v,GLUT_KEY_F4,_SC("GLUT_KEY_F4"));
	RegisterGlobalConstant(v,GLUT_KEY_F5,_SC("GLUT_KEY_F5"));
	RegisterGlobalConstant(v,GLUT_KEY_F6,_SC("GLUT_KEY_F6"));
	RegisterGlobalConstant(v,GLUT_KEY_F7,_SC("GLUT_KEY_F7"));
	RegisterGlobalConstant(v,GLUT_KEY_F8,_SC("GLUT_KEY_F8"));
	RegisterGlobalConstant(v,GLUT_KEY_F9,_SC("GLUT_KEY_F9"));
	RegisterGlobalConstant(v,GLUT_KEY_F10,_SC("GLUT_KEY_F10"));
	RegisterGlobalConstant(v,GLUT_KEY_F11,_SC("GLUT_KEY_F11"));
	RegisterGlobalConstant(v,GLUT_KEY_F12,_SC("GLUT_KEY_F12"));

	RegisterGlobalConstant(v,GLUT_KEY_LEFT,_SC("GLUT_KEY_LEFT"));
	RegisterGlobalConstant(v,GLUT_KEY_UP,_SC("GLUT_KEY_UP"));
	RegisterGlobalConstant(v,GLUT_KEY_RIGHT,_SC("GLUT_KEY_RIGHT"));
	RegisterGlobalConstant(v,GLUT_KEY_DOWN,_SC("GLUT_KEY_DOWN"));
	RegisterGlobalConstant(v,GLUT_KEY_PAGE_UP,_SC("GLUT_KEY_PAGE_UP"));
	RegisterGlobalConstant(v,GLUT_KEY_PAGE_DOWN,_SC("GLUT_KEY_PAGE_DOWN"));
	RegisterGlobalConstant(v,GLUT_KEY_HOME,_SC("GLUT_KEY_HOME"));
	RegisterGlobalConstant(v,GLUT_KEY_END,_SC("GLUT_KEY_END"));
	RegisterGlobalConstant(v,GLUT_KEY_INSERT,_SC("GLUT_KEY_INSERT"));

	RegisterGlobalConstant(v,GLUT_KEY_REPEAT_OFF,_SC("GLUT_KEY_REPEAT_OFF"));
	RegisterGlobalConstant(v,GLUT_KEY_REPEAT_ON,_SC("GLUT_KEY_REPEAT_ON"));
	RegisterGlobalConstant(v,GLUT_KEY_REPEAT_DEFAULT,_SC("GLUT_KEY_REPEAT_DEFAULT"));

	RegisterGlobalConstant(v,GLUT_LEFT_BUTTON,_SC("GLUT_LEFT_BUTTON"));
	RegisterGlobalConstant(v,GLUT_MIDDLE_BUTTON,_SC("GLUT_MIDDLE_BUTTON"));
	RegisterGlobalConstant(v,GLUT_RIGHT_BUTTON,_SC("GLUT_RIGHT_BUTTON"));
	RegisterGlobalConstant(v,GLUT_DOWN,_SC("GLUT_DOWN"));
	RegisterGlobalConstant(v,GLUT_UP,_SC("GLUT_UP"));

	RegisterGlobalConstant(v,GLUT_LEFT,_SC("GLUT_LEFT"));
	RegisterGlobalConstant(v,GLUT_ENTERED,_SC("GLUT_ENTERED"));

	RegisterGlobalConstant(v,GLUT_ACTIVE_SHIFT,_SC("GLUT_ACTIVE_SHIFT"));
	RegisterGlobalConstant(v,GLUT_ACTIVE_CTRL,_SC("GLUT_ACTIVE_CTRL"));
	RegisterGlobalConstant(v,GLUT_ACTIVE_ALT,_SC("GLUT_ACTIVE_ALT"));
	RegisterGlobalConstant(v,GLUT_RED,_SC("GLUT_RED"));
	RegisterGlobalConstant(v,GLUT_GREEN,_SC("GLUT_GREEN"));
	RegisterGlobalConstant(v,GLUT_BLUE,_SC("GLUT_BLUE"));

	// RegisterGlobalConstant(v,GLUT_KEY_DOWN,_SC("GLUT_KEY_DOWN"));
	// RegisterGlobalConstant(v,GLUT_KEY_PAGE_UP,_SC("GLUT_KEY_PAGE_UP"));
	// RegisterGlobalConstant(v,GLUT_KEY_PAGE_DOWN,_SC("GLUT_KEY_PAGE_DOWN"));

	//////////////////////////////////////////////////////////////////////////
	//glut
	RegisterGlobal(v,exit,_SC("exit"));
	RegisterGlobal(v,glutInitWindowPosition,_SC("glutInitWindowPosition"));
	RegisterGlobal(v,glutInitWindowSize,_SC("glutInitWindowSize"));
	RegisterGlobal(v,glutCreateWindow,_SC("glutCreateWindow"));
	RegisterGlobal(v,glutInitDisplayMode,_SC("glutInitDisplayMode"));
	RegisterGlobal(v,glutSwapBuffers,_SC("glutSwapBuffers"));
	RegisterGlobal(v,glutMainLoop,_SC("glutMainLoop"));
	RegisterGlobal(v,glutSolidTeapot,_SC("glutSolidTeapot"));
	RegisterGlobal(v,glutSolidSphere,_SC("glutSolidSphere"));
	RegisterGlobal(v,glutSolidCone,_SC("glutSolidCone"));
	RegisterGlobal(v,glutSetKeyRepeat,_SC("glutSetKeyRepeat"));
	RegisterGlobal(v,glutIgnoreKeyRepeat,_SC("glutIgnoreKeyRepeat"));
	RegisterGlobal(v,glutGetModifiers,_SC("glutGetModifiers"));
	RegisterGlobal(v,glutPostRedisplay,_SC("glutPostRedisplay"));

	RegisterGlobal(v,glLightfv,_SC("glLightfv"));



	register_global_func(v,sq_glutInit,_SC("glutInit"));
	register_global_func(v,sq_glutDisplayFunc,_SC("glutDisplayFunc"));
	register_global_func(v,sq_glutIdleFunc,_SC("glutIdleFunc"));
	register_global_func(v,sq_glutReshapeFunc,_SC("glutReshapeFunc"));

	register_global_func(v,sq_glutKeyboardFunc,_SC("glutKeyboardFunc"));
	register_global_func(v,sq_glutSpecialFunc,_SC("glutSpecialFunc"));
	register_global_func(v,sq_glutKeyboardUpFunc,_SC("glutKeyboardUpFunc"));
	register_global_func(v,sq_glutSpecialUpFunc,_SC("glutSpecialUpFunc"));

	register_global_func(v,sq_glutMotionFunc,_SC("glutMotionFunc"));
	register_global_func(v,sq_glutPassiveMotionFunc,_SC("glutPassiveMotionFunc"));

	register_global_func(v,sq_glutEntryFunc,_SC("glutEntryFunc"));

	REGGLOBALSQFUNC(glutMouseFunc)

}

#endif

